package com.sunfeng.a04;

import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.annotation.InjectionMetadata;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.env.StandardEnvironment;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @Author : 孙峰
 * @Description:
 * @Date : 2022/4/8  14:50
 */
public class DigInAutowired {
    public static void main(String[] args) throws Throwable {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        test(beanFactory);

        Field bean03 = Bean01.class.getDeclaredField("bean03");
        DependencyDescriptor descriptor01 = new DependencyDescriptor(bean03, false);
        Object o = beanFactory.doResolveDependency(descriptor01, null, null, null);
        System.out.println(o);

        Method setBean02 = Bean01.class.getDeclaredMethod("setBean02", Bean02.class);
        DependencyDescriptor descriptor02 = new DependencyDescriptor(new MethodParameter(setBean02, 0), false);
        Object o1 = beanFactory.doResolveDependency(descriptor02, null, null, null);
        System.out.println(o1);


        Method setHome = Bean01.class.getDeclaredMethod("setHome", String.class);
        DependencyDescriptor descriptor03 = new DependencyDescriptor(new MethodParameter(setHome, 0), true);

        Object o2 = beanFactory.doResolveDependency(descriptor03, null, null, null);
        System.out.println(o2);

    }
    private static void  test(DefaultListableBeanFactory beanFactory) throws Throwable {
        beanFactory.registerSingleton("bean02",new Bean02());
        beanFactory.registerSingleton("bean03",new Bean03());
        // @Value
        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        // 解析括号的解析器
        beanFactory.addEmbeddedValueResolver(new StandardEnvironment()::resolvePlaceholders);

        AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();

        processor.setBeanFactory(beanFactory);
        Bean01 bean01 = new Bean01();
//        System.out.println(bean01);
//        processor.postProcessProperties(null,bean01,"bean01");// 执行以来注入  @Autowired @Value
//        System.out.println(bean01);
        Method findAutowiringMetadata =
                AutowiredAnnotationBeanPostProcessor.class.getDeclaredMethod("findAutowiringMetadata", String.class, Class.class, PropertyValues.class);
        findAutowiringMetadata.setAccessible(true);
        InjectionMetadata injectionMetadata = (InjectionMetadata) findAutowiringMetadata.invoke(processor, "bean01", Bean01.class, null);// 获取bean01 @Value @Autowired 的成员变量
        System.out.println(injectionMetadata);
        // 调用 InjectionMetadata 来进行依赖注入，注入时按照类型查找值

        injectionMetadata.inject(bean01,"bean01",null);

        System.out.println(bean01);
    }
}
